/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dp1.titandevelop.titano.helper;


import dp1.titandevelop.titano.bean.EmpleadoEficiencia;
import dp1.titandevelop.titano.bean.EmpleadoSeleccionado;
import dp1.titandevelop.titano.bean.galletaAux;
import dp1.titandevelop.titano.persistent.DetalleDamanda;
import dp1.titandevelop.titano.persistent.EmpleadoXProcesoTurno;
import dp1.titandevelop.titano.persistent.Maquina;
import dp1.titandevelop.titano.persistent.Proceso;
import dp1.titandevelop.titano.persistent.Producto;
import dp1.titandevelop.titano.persistent.ProductoXProceso;
import dp1.titandevelop.titano.persistent.Receta;
import dp1.titandevelop.titano.persistent.Turno;
import dp1.titandevelop.titano.service.AsignacionService;
import dp1.titandevelop.titano.service.TurnoService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;




/**
 *
 * @author naty
 */
public class HelperProcess {
    public static final int SALIDA=1;//1;
    public static final int ENTRADA=0;//2;
    
    public static ArrayList<EmpleadoSeleccionado> ejecutar(ArrayList<EmpleadoXProcesoTurno> listaEmpleado,ArrayList<Proceso> listaProceso,ArrayList<DetalleDamanda> detalleDemanda){
    ArrayList<EmpleadoSeleccionado> solucionInicial;
    ArrayList<EmpleadoSeleccionado> solucionFinal=new ArrayList();
    ArrayList<EmpleadoSeleccionado> listaFinal= new ArrayList();
    TurnoService turnoService=new TurnoService();
    HelperAlgoritmo algoritmo= new HelperAlgoritmo();
    ArrayList<Turno> listaTurnos= turnoService.buscar();
    
////    /*Datos Demanda*/
//    Date fecha=new Date();
//    Demanda demanda=dp1.titandevelop.titano.service.DemandaService.buscarPorFecha(fecha);
//    ArrayList<DetalleDamanda> detalleDemanda=dp1.titandevelop.titano.service.DetalleDeDemandaService.buscarPorIdDemanda(demanda.getIddemanda());
    
 
    /*Datos de galletas*/
    ArrayList<galletaAux> galletas=obtenerGalletas(detalleDemanda);
    ArrayList<ProductoXProceso> productoProceso=obtenerProductoProceso(listaProceso);
    ArrayList<ProductoXProceso> productoProcesoSalida=obtenerTipo(productoProceso,SALIDA);
    
    /*Hallar Recetas*/
    ArrayList<Receta> listaReceta= dp1.titandevelop.titano.service.RecetaService.BuscarTodosProductosTerminados();
    
    
    /*Se trabajara con tres turnos fijos : Mañana-Tarde-Noche*/
    for(int i=0;i<3;i++){
         ArrayList<EmpleadoXProcesoTurno> listaEmpleadoProceso=hallarEmpleadoXTurno(listaEmpleado,listaTurnos.get(i).getIdturno());
        if(!listaEmpleadoProceso.isEmpty()){
             try {
                 
                 solucionInicial= algoritmo.grasp(listaEmpleadoProceso,listaProceso,galletas,productoProcesoSalida,listaReceta);
                 if (solucionInicial.isEmpty()) continue;
                 solucionFinal= algoritmo.tabuSearch(solucionInicial, listaEmpleadoProceso);
               
                 solucionFinal=algoritmo.completarProductosIntermedios(solucionFinal,listaEmpleadoProceso);
                 listaFinal.addAll(solucionFinal);
             } catch (InterruptedException ex) {
                 Logger.getLogger(HelperProcess.class.getName()).log(Level.SEVERE, null, ex);
             }
   
             actualizarDemanda(solucionFinal,galletas);
        }
        
        
        
    }
    
    return listaFinal; 
    }
    
    public static ArrayList<EmpleadoXProcesoTurno> hallarEmpleadoXProceso(ArrayList<EmpleadoEficiencia> listaEmpleado, int turno) {
       ArrayList<EmpleadoXProcesoTurno> empleadoProceso= new ArrayList();
       
        for(int i=0; i<listaEmpleado.size();i++){
            ArrayList<EmpleadoXProcesoTurno> aux=dp1.titandevelop.titano.service.EmpleadoXProcesoTurnoService.buscarPorIdEmpleadoTurno(listaEmpleado.get(i).getE().getIdempleado(),turno);
            if(!aux.isEmpty()){
                empleadoProceso.addAll(aux);
            }
        }
        
        return empleadoProceso;  
    }
 
    public static void guardarSolucion(ArrayList<EmpleadoSeleccionado> listaFinal,int indice, String descripcion) {
    AsignacionService service=new AsignacionService();
    ArrayList<EmpleadoSeleccionado> solucionTurno;    
        for(int j=0; j<3;j++){
            solucionTurno=hallarSolucionPorTurno(listaFinal,j+1);
            ArrayList<Maquina> maquina=dp1.titandevelop.titano.service.MaquinaService.buscar();
            Maquina m=new Maquina();

            for(int i=0;i<solucionTurno.size();i++){

                for(int k=0; k<maquina.size();k++){
                    if(maquina.get(k).getToProceso().getIdproceso().equals(solucionTurno.get(i).getEmpleadoProceso().getToProceso().getIdproceso())){
                        m=maquina.get(k);
                        maquina.remove(k);
                        break;
                    }
                }
            
                service.insertar(solucionTurno.get(i).getEmpleadoProceso().getToTurno().getIdturno(),
                        solucionTurno.get(i).getEmpleadoProceso().getToEmpleado().getIdempleado(),
                        m.getIdmaquina(),solucionTurno.get(i).getGalleta(),
                        solucionTurno.get(i).getBeneficio(),
                        solucionTurno.get(i).getCosto(),indice,descripcion);

            }
        }
        
    }
    
    private static ArrayList<EmpleadoXProcesoTurno> hallarEmpleadoXTurno(ArrayList<EmpleadoXProcesoTurno> listaEmpleado, int idTurno) {
        ArrayList<EmpleadoXProcesoTurno> aux=new ArrayList();
        
        for(int i=0;i<listaEmpleado.size();i++){
            if(listaEmpleado.get(i).getToTurno().getIdturno()==idTurno){
                aux.add(listaEmpleado.get(i));
            }
        }
        
        return aux;
    }

    public static void asignar(int anio, int mes, int idAsignacion) {
        AsignacionService servicio= new AsignacionService();      
         servicio.desasignar();
         servicio.asignar(idAsignacion,anio,mes);
    }
    
     /*Obtener galletas*/
    public static ArrayList<galletaAux> obtenerGalletas(ArrayList<DetalleDamanda> detalleDemanda) {
     ArrayList<Producto> galletasAux=dp1.titandevelop.titano.service.ProductoService.buscarGalleta();
       ArrayList<galletaAux> aux=new ArrayList();
       
       /*Busca demanda por Producto*/
        for(int i=0;i<galletasAux.size();i++){
            galletaAux auxgalleta=new galletaAux();
            auxgalleta.setGalleta(galletasAux.get(i));
            auxgalleta.setDemanda(buscarDemanda(galletasAux.get(i).getIdproducto(),detalleDemanda)/30);
            auxgalleta.setBeneficio(galletasAux.get(i).getBeneficio()*auxgalleta.getDemanda());
            aux.add(auxgalleta);
        }
        
        /*Ordenamos arreglo de galleta por beneficio*/
        Comparator comparador = new Comparator<galletaAux>() {
            @Override
            public int compare(galletaAux e1, galletaAux e2) {
                if (e1.getBeneficio() >= e2.getBeneficio()) {
                    return -1;
                } 
                if (e1.getBeneficio() < e2.getBeneficio()) {
                    return +1;
                } 
                return 1;
            }
        };
        
        /* Ordena por un quicksort*/
        Collections.sort(aux, comparador);
        return aux;

    }
    
    /*Buscar demanda para cada producto*/
    public static int buscarDemanda(int idProducto,ArrayList<DetalleDamanda> detalleDemanda) {
        for(int i=0;i<detalleDemanda.size();++i){
            if(detalleDemanda.get(i).getToProducto().getIdproducto()==idProducto)
                return detalleDemanda.get(i).getCantidad();
            
        }
        
         return 0;
    
    }
   
    /*Obtener productos por procesos*/
    private static ArrayList<ProductoXProceso> obtenerProductoProceso(ArrayList<Proceso> listaProceso) {
        ArrayList<ProductoXProceso> p=dp1.titandevelop.titano.service.ProductoXProcesoService.buscar();
        for(int i=0;i<p.size();i++){
            for(int k=0;k<listaProceso.size();k++){
                if(p.get(i).getToProceso().getIdproceso().equals(listaProceso.get(k).getIdproceso())){
                    p.get(i).getToProceso().setCantidadmaquina(listaProceso.get(k).getCantidadmaquina());
                }
            }
        }
        
        return p;
    }

    private static void actualizarDemanda(ArrayList<EmpleadoSeleccionado> solucionFinal, ArrayList<galletaAux> galletas) {
      
      
        for(int i=0;i<galletas.size();i++){
            int demanda=0;
            for(int j=0;j<solucionFinal.size();j++){
                if(galletas.get(i).getGalleta().getIdproducto().equals(solucionFinal.get(j).getGalleta())
                        && solucionFinal.get(j).getEmpleadoProceso().getToProceso().getIdproceso()==4){
                    demanda+= solucionFinal.get(j).getEmpleadoProceso().getProductividad();
                
                }
            
            
            }
            
            galletas.get(i).setDemanda(galletas.get(i).getDemanda()-demanda);
        
        }
    }

    private static ArrayList<ProductoXProceso> obtenerTipo(ArrayList<ProductoXProceso> productoProceso, int tipo) {
        ArrayList<ProductoXProceso> aux=new ArrayList();
        for(int i=0;i<productoProceso.size();i++){
            if(productoProceso.get(i).getTipomovimiento().equals(tipo)){
                aux.add(productoProceso.get(i));
            }

        }
        
       return aux;
    }

    private static ArrayList<EmpleadoSeleccionado> hallarSolucionPorTurno(ArrayList<EmpleadoSeleccionado> listaFinal, int turno) {
        ArrayList<EmpleadoSeleccionado> aux=new ArrayList();
        for(int i=0;i<listaFinal.size();i++){
            if(listaFinal.get(i).getEmpleadoProceso().getToTurno().getIdturno().equals(turno)){
                aux.add(listaFinal.get(i));
            }
        }
        return aux;
    }

    
}
